package net.towee.client.com.dashboard.view;

import java.util.ArrayList;
import java.util.List;

import net.towee.client.com.dashboard.presenter.BoardEditorPresenter.Display;
import net.towee.client.i18n.ToweeConstants;
import net.towee.client.resources.ClientResource;
import net.towee.client.widgets.ExtFlowPanel;
import net.towee.client.widgets.LeftTabsWidget;
import net.towee.client.widgets.SpanPanel;
import net.towee.model.group.GroupIdentity;

import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.HasAllMouseHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;

public class BoardEditorView extends PopupPanel implements Display {

	/**
	 * Control tabs
	 * @author c58
	 */
	private class TabsContainer extends LeftTabsWidget {
		private final Widget info;
		private final Widget groups;
		
		public TabsContainer(ClientResource resource) {
			super(resource);
			this.getElement().setAttribute("tabs", "");
			
			// Create tabs
			info = addTab(constants.information(), true);
			groups = addTab(constants.groups());
		}
		
		@Override
		public void onClick(ClickEvent event) {
			super.onClick(event);
			
			tabContainer.clear();
			if(event.getSource().equals(info))
				tabContainer.add(boardEditor);
			else
				tabContainer.add(groupsEditor);
		}
	}
	
	/**
	 * Edit attached groups
	 * @author c58
	 */
	private class GroupsEditor extends FlowPanel {
		public List<GroupIdentity> attachedGroups = new ArrayList<GroupIdentity>();
		
		private final FlowPanel availColumn;
		private final FlowPanel attColumn;
		private final FlowPanel arrow;
		
		public GroupsEditor() {
			this.availColumn = new FlowPanel();
			this.attColumn = new FlowPanel();
			this.arrow = new FlowPanel();
			
			// Set style for editor
			setStyleName( resource.css().dashBoardGroupsEditor() );
			
			// Create columns
			createColumn(availColumn, true);
			createColumn(attColumn, false);
			
			// Create separator
			createSeparator();
		}

		private void createSeparator() {
			FlowPanel sep = new FlowPanel();
			sep.getElement().setAttribute("separator", "");
			add(sep);
		}

		private void createColumn(FlowPanel column, boolean left) {
			// Create column name label
			Label label = new Label( (left)?constants.dashBoardAvailGroups():constants.dashBoardAttGroups());
			label.getElement().removeAttribute("class");
			label.getElement().setAttribute("columnLabel", (left)?"left":"right");
			add(label);
			
			column.getElement().setAttribute("column", (left)?"left":"right");
			add(column);
		}
		
		private HasAllMouseHandlers getGroupItem( GroupIdentity idnt ) {
			ExtFlowPanel item = new ExtFlowPanel();
			item.getElement().setAttribute("item", "group");
			item.add( new ExtFlowPanel( idnt.getPrintName() ) );
			item.add( new SpanPanel( idnt.getAlias() ) );
			
			return item;
		}
		
		public void addAvailableGroup(final GroupIdentity idnt, final boolean att) {
			final HasAllMouseHandlers item = getGroupItem( idnt );
			
			if(!att) {
				availColumn.add( (Widget)item );
				attachedGroups.remove( idnt );
			}
			else {
				attColumn.add( (Widget)item );
				attachedGroups.add(idnt);
			}
			
			item.addMouseOverHandler(new MouseOverHandler() {
				@Override
				public void onMouseOver(MouseOverEvent event) {
					double h = ((Widget)item).getElement().getOffsetHeight()/2;
					
					if(!att) {
						arrow.getElement().setAttribute("arrow", "toRight");
						arrow.getElement().getStyle().setProperty("borderLeft", "10px solid #eee");
						arrow.getElement().getStyle().setProperty("borderRight", "none");
						availColumn.add(arrow);
					}	else {
						arrow.getElement().setAttribute("arrow", "toLeft");
						arrow.getElement().getStyle().setProperty("borderLeft", "none");
						arrow.getElement().getStyle().setProperty("borderRight", "10px solid #eee");
						attColumn.add(arrow);
					}
					
					arrow.getElement().getStyle().setTop( ((Widget)item).getElement().getOffsetTop(), Unit.PX);
					arrow.getElement().getStyle().setProperty("borderTop", h+"px solid white");
					arrow.getElement().getStyle().setProperty("borderBottom", h+"px solid white");
				}
			});
			item.addMouseOutHandler(new MouseOutHandler() {
				@Override
				public void onMouseOut(MouseOutEvent event) {
					arrow.removeFromParent();
				}
			});
			item.addMouseUpHandler(new MouseUpHandler() {
				@Override
				public void onMouseUp(MouseUpEvent event) {
					arrow.removeFromParent();
					
					if(!att)
						addAvailableGroup( idnt, true );
					else 
						addAvailableGroup( idnt, false );
					
					((Widget)item).removeFromParent();
				}
			});
		}
		
	}
	
	/**
	 * Edit board name and other options in the future
	 * @author c58
	 */
	private class BoardEditor extends FlowPanel {
		public final TextBox boardName = new TextBox();
		
		public BoardEditor() {
			// Create table
			FlexTable table = new FlexTable();
			FlexCellFormatter cellFormatter = table.getFlexCellFormatter();
			table.addStyleName( resource.css().dataForm() );
			table.setCellSpacing(6);			
			   
			// Add some standard form options
			table.setWidget(0, 0, getRowName( constants.dashBoardName(), constants.dashBoardExample()));
			table.setWidget(0, 1, boardName);

			add(table);
		}
		
		protected FlowPanel getRowName(String name, String desc){
			FlowPanel row = new FlowPanel();
			
			ExtFlowPanel nameSpan = new ExtFlowPanel(name);
			ExtFlowPanel descSpan = new ExtFlowPanel(desc);

			nameSpan.getElement().setAttribute("row", "name");
			descSpan.getElement().setAttribute("row", "desc");
			
			row.add(nameSpan);
			row.add(descSpan);
			
			return row;
		}
	}
	
	private final ToweeConstants constants;
	private final ClientResource resource;
	
	private final TabsContainer tabs;
	private final GroupsEditor groupsEditor;
	private final BoardEditor boardEditor;
	private final FlowPanel tabContainer;
	
	// Areas
	private final TextBox name = new TextBox();
	private final Button applyButton = new Button();
	private final Button deleteButton = new Button();
	
	@Inject
	public BoardEditorView(ToweeConstants constants, ClientResource resource) {
		super(true);
		
		this.constants = constants;
		this.resource = resource;
		
		this.tabs = new TabsContainer( resource );
		this.groupsEditor = new GroupsEditor();
		this.boardEditor = new BoardEditor();
		this.tabContainer = new FlowPanel();
		
		applyButton.setText( constants.done() );
		deleteButton.setText( constants.delete() );
		deleteButton.setVisible( false );
		
		this.setStyleName( resource.css().dashBoardEditor() );
		tabContainer.getElement().setAttribute("content", "");
		tabContainer.add( boardEditor );
		
		setAnimationEnabled( false );
		setGlassEnabled(true);
		setGlassStyleName( resource.css().loadingBarGlass() );
		
		FlowPanel container = new FlowPanel();
		container.add( tabs );
		container.add( tabContainer );
		
		// Add buttons
		FlowPanel buttons = new FlowPanel();
		buttons.getElement().setAttribute("buttons", "");
		applyButton.setStyleName( resource.css().lobbyNextStepButton() );
		applyButton.setWidth("100%");
		buttons.add(applyButton);
		
		deleteButton.setStyleName( resource.css().lobbyCloseButton() );
		deleteButton.setWidth("100%");
		buttons.add(deleteButton);
		container.add(buttons);
		
		setWidget( container );
	}
	
	@Override
	public void showEditor(){
		// Show it
		show();
		
		// Center it
		getElement().getStyle().setProperty("left", "50%");
		getElement().getStyle().setProperty("marginLeft", "-"+(getElement().getOffsetWidth()/2)+"px");
		getElement().getStyle().setProperty("top", "50%");
		getElement().getStyle().setProperty("marginTop", "-"+(getElement().getOffsetHeight()/2)+"px");
	}
	
	@Override
	public void setName(String n) {
		boardEditor.boardName.setText( n );
		deleteButton.setVisible( true );
	}

	@Override
	public String getName() {
		return boardEditor.boardName.getValue();
	}

	@Override
	public void setAttachedGroups(List<GroupIdentity> groups) {
		for(GroupIdentity id : groups) {
			groupsEditor.addAvailableGroup(id, true);	
		}
	}

	@Override
	public List<GroupIdentity> getAttachedGroups() {
		return groupsEditor.attachedGroups;
	}

	@Override
	public void setAvailableGroups(List<GroupIdentity> groups) {
		for(GroupIdentity id : groups) {
			groupsEditor.addAvailableGroup(id, false);	
		}
	}

	@Override
	public HasClickHandlers getApplyButton() {
		return applyButton;
	}

	@Override
	public HasClickHandlers getDeleteButton() {
		return deleteButton;
	}

	@Override
	public void emptyName() {

	}

	@Override
	public void existsName() {

	}

	@Override
	public void onBoardOperationDone() {
		hide();
	}
}